package cn.springcloud.fix.gateway.service.impl;

import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Service
@AllArgsConstructor
public class TestGatewayService implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;
    private RouteDefinitionWriter routeDefinitionWriter;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    /**
     * predicate.setName(“Path”); 设置predicat名称，这个名称不是乱起的，
     * Spring会根据名称去查找对应的FilterFactory，
     * 目前支持的名称有：After、Before、Between、Cookie、Header、Host、Method、Path、Query、RemoteAddr。
     */
    public String save() {
        PredicateDefinition predicateDefinition = new PredicateDefinition();
        predicateDefinition.setName("Path");

        Map<String, String> predicateParams = new HashMap<>(8);
        //在包org.springframework.cloud.gateway.handler.predicate里有Spring Cloud Gateway所有的Predicate，
        // 打开对应的RoutePredicateFactory，内部类Config就是该Predicate支持的参数
        predicateParams.put("pattern", "/rate/**");
        predicateDefinition.setArgs(predicateParams);

        Map<String, String> filterParams = new HashMap<>(8);
        FilterDefinition filterDefinition = new FilterDefinition();
        // 名称是固定的，spring gateway会根据名称找对应的FilterFactory
        filterDefinition.setName("RequestRateLimiter");
        // 每秒最大访问次数
        filterParams.put("redis-rate-limiter.replenishRate", "2");
        // 令牌桶最大容量
        filterParams.put("redis-rate-limiter.burstCapacity", "3");
        // 限流策略(#{@BeanName})
        filterParams.put("key-resolver", "#{@pathKeyResolver}");
        // 自定义限流器(#{@BeanName})
        //filterParams.put("rate-limiter", "#{@redisRateLimiter}");
        filterDefinition.setArgs(filterParams);

        // URI uri = UriComponentsBuilder.fromHttpUrl("http://www.baidu.com").build().toUri();
        URI uri = UriComponentsBuilder.fromUriString("lb://HELLO-SERVICE").build().toUri();

        RouteDefinition routeDefinition = new RouteDefinition();
        routeDefinition.setId("rateLimitTest");//设置definition的id，需要全局唯一，默认使用UUID。
        routeDefinition.setPredicates(Collections.singletonList(predicateDefinition));
        routeDefinition.setFilters(Collections.singletonList(filterDefinition));
        routeDefinition.setUri(uri);

        // 默认的RouteDefinitionWriter实现类是org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository。
        // 注意最后一定要调用subscribe()，否则不执行。
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }
}
